home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Technical Documentation / Sample Code / DTS.Lib & Samples / DTS.Lib / Utilities.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-22  |  69.2 KB  |  2,546 lines  |  [TEXT/MPS ]

  1. /*
  2. **    Apple Macintosh Developer Technical Support
  3. **
  4. **    Collection of Utilities for DTS Sample code
  5. **
  6. **    Program:    Utilities.c.o
  7. **    File:        Utilities.c
  8. **
  9. **    Copyright © 1988-1991 Apple Computer, Inc.
  10. **    All rights reserved.
  11. */
  12.  
  13.  
  14. #ifndef THINK_C
  15.  
  16. #ifndef __CONTROLS__
  17. #include <Controls.h>
  18. #endif
  19.  
  20. #ifndef __DESK__
  21. #include <Desk.h>
  22. #endif
  23.  
  24. #ifndef __DEVICES__
  25. #include <Devices.h>
  26. #endif
  27.  
  28. #ifndef __EVENTS__
  29. #include <Events.h>
  30. #endif
  31.  
  32. #ifndef __FONTS__
  33. #include <Fonts.h>
  34. #endif
  35.  
  36. #ifndef __MENUS__
  37. #include <Menus.h>
  38. #endif
  39.  
  40. #ifndef __NOTIFICATION__
  41. #include <Notification.h>
  42. #endif
  43.  
  44. #ifndef __OSEVENTS__
  45. #include <OSEvents.h>
  46. #endif
  47.  
  48. #ifndef __RESOURCES__
  49. #include <Resources.h>
  50. #endif
  51.  
  52. #ifndef __SCRIPT__
  53. #include <Script.h>
  54. #endif
  55.  
  56. #ifndef __STDLIB__
  57. #include <StdLib.h>
  58. #endif
  59.  
  60. #ifndef __SEGLOAD__
  61. #include <SegLoad.h>
  62. #endif
  63.  
  64. #ifndef __STRINGS__
  65. #include <Strings.h>
  66. #endif
  67.  
  68. #ifndef __SYSEQU__
  69. #include <SysEqu.h>
  70. #endif
  71.  
  72. #ifndef __TEXTEDIT__
  73. #include <TextEdit.h>
  74. #endif
  75.  
  76. #ifndef __TOOLUTILS__
  77. #include <ToolUtils.h>
  78. #endif
  79.  
  80. #endif    /* Think C */
  81.  
  82. #ifndef __APPLEEVENTS__
  83. #include <AppleEvents.h>
  84. #endif
  85.  
  86. #ifndef __COMPONENTS__
  87. #include <Components.h>
  88. #endif
  89.  
  90. #ifndef __FIXMATH__
  91. #include <FixMath.h>
  92. #endif
  93.  
  94. #ifndef __GESTALTEQU__
  95. #include <GestaltEqu.h>
  96. #endif
  97.  
  98. #ifndef __FOLDERS__
  99. #include <Folders.h>
  100. #endif
  101.  
  102. #ifndef __MOVIES__
  103. #include <Movies.h>
  104. #endif
  105.  
  106. #ifndef __PACKAGES__
  107. #include <Packages.h>
  108. #endif
  109.  
  110. #ifndef __PALETTES__
  111. #include <Palettes.h>
  112. #endif
  113.  
  114. #ifndef __STRING__
  115. #include <String.h>
  116. #endif
  117.  
  118. #ifndef __TRAPS__
  119. #include <Traps.h>
  120. #endif
  121.  
  122. #include "Utilities.h"
  123.  
  124.  
  125.  
  126. /*****************************************************************************/
  127.  
  128.  
  129.  
  130. /* Global variables -- See Utilities.h for more explanation. */
  131.  
  132. short            gMachineType;            /* which machine this is */
  133. short            gSystemVersion;            /* System version number */
  134. short            gProcessorType;            /* which CPU this is */
  135. Boolean            gHasFPU;                /* true if machine has an FPU */
  136. short            gQDVersion;                /* major QD version #; 0 for original,
  137.                                                     1 for color QD, 2 for 32-bit QD */
  138. short            gKeyboardType;            /* which type of keyboard is present */
  139. short            gAppleTalkVersion;        /* AppleTalk version number */
  140. Boolean            gHasPMMU;                /* true if machine has a PMMU or equivalent */
  141. short            gAUXVersion;            /* major A/UX version number (0 if not present) */
  142.  
  143. Boolean            gHasWaitNextEvent;
  144. short            gAppResRef;
  145. Boolean            gInBackground;
  146. Str255            gAppName;
  147. OSType            gSignature = '????';
  148. Boolean            gHaveSystemInfo;
  149.  
  150. long            gQTVersion;                    /* QuickTime version (0 means not available). */
  151. Component        gMovieControllerComponent;    /* QuickTime movie controller component reference. */
  152.                                             /* Call InitQuickTime to initialize these globals. */
  153.  
  154.  
  155. static Handle    gScrollProc = nil;
  156. static Handle    gButtonProcs[3] = {nil, nil, nil};
  157.  
  158.  
  159.  
  160. /*****************************************************************************/
  161.  
  162.  
  163.  
  164. /* Given an alert ID and a window pointer the alert relates to, this function
  165. ** will center the alert’s rectangle before showing it on the proper screen.
  166. ** This follows the Apple Human Interface Guidelines for where to place a
  167. ** centered window on the screen.  If the alert is not closely associated with
  168. ** another window, pass a nil for the window pointer of the related window.  If
  169. ** you pass a nil, the alert is simply displayed where the resource
  170. ** would indicate.  Note that if an error occurs when getting the resource for
  171. ** the alert, then the alert is not displayed, and the returned value is not
  172. ** the item hit, but is the error that occured when reading the resource. */
  173.  
  174. #pragma segment UtilMain
  175. short    CenteredAlert(short alertID, WindowPtr relatedWindow, ModalFilterProcPtr filter)
  176. {
  177.     AlertTHndl    alertHandle;
  178.     WindowPtr    tempWindow;
  179.     Rect        alertRect, sizeInfo;
  180.     short        itemHit;
  181.     char        hstate;
  182.     OSErr        err;
  183.  
  184.     itemHit = 1;
  185.  
  186.     if (!SimpleCanDialog()) {
  187.         alertHandle = (AlertTHndl)GetAppResource('ALRT', alertID, &err);
  188.         if (err) return((short)err);
  189.  
  190.         hstate = LockHandleHigh((Handle)alertHandle);
  191.             /* Do our part to help prevent fragmentation. */
  192.  
  193.         alertRect = (*alertHandle)->boundsRect;
  194.             /* Preserve the real alert bounding rectangle. */
  195.  
  196.         if (tempWindow = NewWindow(nil, &alertRect, "\p", false, dBoxProc,
  197.                                   (WindowPtr)nil, false, 0)) {
  198.             /* Use an invisible temporary window to calculate where the alert will go. */
  199.  
  200.             SetRect(&sizeInfo, 0, 0, 0, 0);
  201.             (*alertHandle)->boundsRect = CenterWindow(tempWindow, relatedWindow, sizeInfo);
  202.             DisposeWindow(tempWindow);
  203.         }
  204.  
  205.         itemHit = Alert(alertID, filter);
  206.  
  207.         (*alertHandle)->boundsRect = alertRect;
  208.             /* Restore the resource's bounding rect, so if this resource is ever used
  209.             ** not through this function, it will open where the resource indicates. */
  210.  
  211.         HSetState((Handle)alertHandle, hstate);
  212.     }
  213.  
  214.     return(itemHit);
  215. }
  216.  
  217.  
  218.  
  219. /*****************************************************************************/
  220.  
  221.  
  222.  
  223. /* Given two rects, this function centers the second one within the first. */
  224.  
  225. #pragma segment UtilMain
  226. void    CenterRectInRect(Rect outerRect, Rect *innerRect)
  227. {
  228.     PositionRectInRect(outerRect, innerRect, FixRatio(1, 2), FixRatio(1, 2));
  229. }
  230.  
  231.  
  232.  
  233. /*****************************************************************************/
  234.  
  235.  
  236.  
  237. /* Center a window within a particular device.  The device to center the window
  238. ** within is determined by passing a related window.  This allows related
  239. ** windows to be kept on the same device.  This is useful if an alert is related
  240. ** to a specific window, for example. */
  241.  
  242. #pragma segment UtilMain
  243. Rect    CenterWindow(WindowPtr window, WindowPtr relatedWindow, Rect sizeInfo)
  244. {
  245.     WindowPtr    whichDevice;
  246.     Rect        deviceRect, oldWindowRect, newWindowRect, contentRect;
  247.     short        h, v, hh, vv;
  248.  
  249.     if (!(whichDevice = relatedWindow))
  250.         whichDevice = window;
  251.             /* If we have a window to center against, use the device for that window,
  252.             ** else use the device for the window that is getting centered. */
  253.  
  254.     deviceRect = GetWindowDeviceRectNMB(whichDevice);
  255.         /* We now have the rectangle of the device we want to center within. */
  256.  
  257.     contentRect = GetWindowContentRect(window);        /* Get where the window is now. */
  258.     h = hh = contentRect.right  - contentRect.left;
  259.     v = vv = contentRect.bottom - contentRect.top;
  260.     if (sizeInfo.left)
  261.         if (h < sizeInfo.left)
  262.             h = sizeInfo.left;
  263.     if (sizeInfo.right)
  264.         if (h > sizeInfo.right)
  265.             h = sizeInfo.right;
  266.     if (sizeInfo.top)
  267.         if (v < sizeInfo.top)
  268.             v = sizeInfo.top;
  269.     if (sizeInfo.bottom)
  270.         if (v > sizeInfo.bottom)
  271.             v = sizeInfo.bottom;
  272.     contentRect.right  = contentRect.left + h;
  273.     contentRect.bottom = contentRect.top  + v;
  274.  
  275.     oldWindowRect = GetWindowStructureRect(window);
  276.     oldWindowRect.right  += (h - hh);
  277.     oldWindowRect.bottom += (v - vv);
  278.     newWindowRect = oldWindowRect;
  279.  
  280.     PositionRectInRect(deviceRect, &newWindowRect, FixRatio(1, 2), FixRatio(1, 3));
  281.         /* Figure out the new window strucRect so we can compare it against
  282.         ** the old strucRect.  This will tell us how much to move the window. */
  283.  
  284.     OffsetRect(&contentRect, newWindowRect.left - oldWindowRect.left,
  285.                             newWindowRect.top  - oldWindowRect.top);
  286.         /* Calculate the new content rect. */
  287.  
  288.     MoveWindow(window, contentRect.left, contentRect.top, false);
  289.         /* Move the window to the new location. */
  290.  
  291.     return(contentRect);
  292. }
  293.  
  294.  
  295.  
  296. /*****************************************************************************/
  297.  
  298.  
  299.  
  300. /* Close a window.  This handles desk accessory and application windows.  Use
  301. ** this call (instead of DisposeAnyWindow) if the memory for the window was
  302. ** allocated by you.  (Same as CloseWindow v.s. DisposeWindow.) */
  303.  
  304. #pragma segment UtilMain
  305. void    CloseAnyWindow(WindowPtr window)
  306. {
  307.     if (IsDAWindow(window))
  308.         CloseDeskAcc(((WindowPeek)window)->windowKind);
  309.     else {
  310.         if (IsAppWindow(window))
  311.             CloseWindow(window);
  312.         else if (((WindowPeek)window)->windowKind >= dialogKind)
  313.             CloseDialog((DialogPtr)window);
  314.     }
  315. }
  316.  
  317.  
  318.  
  319. /*****************************************************************************/
  320.  
  321.  
  322.  
  323. /* Dispose a window.  This handles desk accessory and application windows.  Use
  324. ** this call (instead of CloseAnyWindow) if you want the memory for the window
  325. ** record to be disposed of.  (Same as CloseWindow v.s. DisposeWindow.) */
  326.  
  327. #pragma segment UtilMain
  328. void    DisposeAnyWindow(WindowPtr window)
  329. {
  330.     if (IsDAWindow(window))
  331.         CloseDeskAcc(((WindowPeek)window)->windowKind);
  332.     else {
  333.         if (IsAppWindow(window))
  334.             DisposeWindow(window);
  335.         else if (((WindowPeek)window)->windowKind >= dialogKind)
  336.             DisposDialog((DialogPtr)window);
  337.     }
  338. }
  339.  
  340.  
  341.  
  342. /*****************************************************************************/
  343.  
  344.  
  345.  
  346. /* Display an alert that tells the user an error occurred, then exit the
  347. ** program.  This function is used as an ultimate bail-out for serious errors
  348. ** that prohibit the continuation of the application.  Errors that do not
  349. ** require the termination of the application should be handled in a different
  350. ** manner. */
  351.  
  352. #pragma segment UtilMain
  353. void    DeathAlert(short errResID, short errStringIndex)
  354. {
  355.     ErrorAlert(errResID, errStringIndex);
  356.     ExitToShell();
  357. }
  358.  
  359.  
  360.  
  361. /*****************************************************************************/
  362.  
  363.  
  364.  
  365. /* Display an alert that tells the user an error occurred, then exit the
  366. ** program.  This function is used as an ultimate bail-out for serious errors
  367. ** that prohibit the continuation of the application.  Errors that do not
  368. ** require the termination of the application should be handled in a different
  369. ** manner.  The message parameter is an error code that is to be displayed. */
  370.  
  371. #pragma segment UtilMain
  372. void    DeathAlertMessage(short errResID, short errStringIndex, short message)
  373. {
  374.     ErrorAlertMessage(errResID, errStringIndex, message);
  375.     ExitToShell();
  376. }
  377.  
  378.  
  379.  
  380. /*****************************************************************************/
  381.  
  382.  
  383.  
  384. /* Display an alert that tells the user an error occurred. */
  385.  
  386. #pragma segment UtilMain
  387. void    ErrorAlert(short errResID, short errStringIndex)
  388. {
  389.     ErrorAlertMessage(errResID, errStringIndex, 0);
  390. }
  391.  
  392.  
  393.  
  394. /*****************************************************************************/
  395.  
  396.  
  397.  
  398. /* Display an alert to inform the user of an error.  errStringIndex acts as an
  399. ** index into a STR# resource of error messages.  If no errStringIndex is
  400. ** given, i.e. = 0, then use a standard message.  If message is not noErr then
  401. ** display it as well.
  402. **
  403. ** BUG NOTE:  GetIndString returns a bogus String if the index is
  404. **            not positive. */
  405.  
  406. #pragma segment UtilMain
  407. void    ErrorAlertMessage(short errResID, short errStringIndex, short message)
  408. {
  409.     Str255    msg1, msg2;
  410.  
  411.     SetCursor(&QD(arrow));
  412.  
  413.     if (errStringIndex <= 0) {
  414.         errStringIndex = eStandardErr;
  415.         errResID = rUtilStrings;
  416.     }
  417.     GetIndString(msg1, errResID, errStringIndex);
  418.  
  419.     if (message == noErr) {
  420.         ParamText(msg1, "\p", "\p", "\p");
  421.         CenteredAlert(rUtilErrorAlert, nil, nil);
  422.     } else {
  423.         NumToString(message, msg2);
  424.         ParamText(msg1, msg2, "\p", "\p");
  425.         CenteredAlert(rUtilErrorMessageAlert, nil, nil);
  426.     }
  427. }
  428.  
  429.  
  430.  
  431. /*****************************************************************************/
  432.  
  433.  
  434.  
  435. /* FindSysFolder returns the (real) vRefNum, and the DirID of the current
  436. ** system folder.  It uses the Folder Manager if present, otherwise it falls
  437. ** back to SysEnvirons.  It returns zero on success, otherwise a standard
  438. ** system error. */
  439.  
  440. #pragma segment UtilMain
  441. OSErr    FindSysFolder(short *foundVRefNum, long *foundDirID)
  442. {
  443.     long            gesResponse;
  444.     SysEnvRec        envRec;
  445.     WDPBRec            myWDPB;
  446.     unsigned char    volName[34];
  447.     OSErr            err;
  448.  
  449.     *foundVRefNum = 0;
  450.     *foundDirID = 0;
  451.     if (!Gestalt(gestaltFindFolderAttr, &gesResponse) &&
  452.         BTstQ(gesResponse, gestaltFindFolderPresent)) {        /* Does Folder Manager exist? */
  453.             err = FindFolder(kOnSystemDisk, kSystemFolderType, kDontCreateFolder,
  454.                 foundVRefNum, foundDirID);
  455.     } else {
  456.         /* Gestalt can't give us the answer, so we resort to SysEnvirons */
  457.         if (!(err = SysEnvirons(curSysEnvVers, &envRec))) {
  458.             myWDPB.ioVRefNum = envRec.sysVRefNum;
  459.             volName[0] = '\000';                    /* Zero volume name */
  460.             myWDPB.ioNamePtr = volName;
  461.             myWDPB.ioWDIndex = 0;
  462.             myWDPB.ioWDProcID = 0;
  463.             if (!(err = PBGetWDInfo(&myWDPB, 0))) {
  464.                 *foundVRefNum = myWDPB.ioWDVRefNum;
  465.                 *foundDirID = myWDPB.ioWDDirID;
  466.             }
  467.         }
  468.     }
  469.     return(err);
  470. }
  471.  
  472.  
  473.  
  474. /*****************************************************************************/
  475.  
  476.  
  477.  
  478. /* GetAppIndResource gets a resource from the application's resource file
  479. ** by index. */
  480.  
  481. #pragma segment UtilMain
  482. Handle    GetAppIndResource(ResType theType, short index, OSErr *err)
  483. {
  484. #pragma unused (err)
  485.  
  486.     short    savedResFile;
  487.     Handle    returnHandle;
  488.  
  489.     savedResFile = CurResFile();
  490.     UseResFile(gAppResRef);
  491.     returnHandle = Get1IndResource(theType, index);
  492.     UseResFile(savedResFile);
  493.     return(returnHandle);
  494. }
  495.  
  496.  
  497.  
  498. /*****************************************************************************/
  499.  
  500.  
  501.  
  502. /* GetAppNamedResource gets a resource from the application's resource file
  503. ** by name. */
  504.  
  505. #pragma segment UtilMain
  506. Handle    GetAppNamedResource(ResType theType, StringPtr name, OSErr *err)
  507. {
  508.     short    savedResFile;
  509.     Handle    returnHandle;
  510.  
  511.     savedResFile = CurResFile();
  512.     UseResFile(gAppResRef);
  513.     returnHandle = Get1NamedResource(theType, name);
  514.     *err = ResError();
  515.     UseResFile(savedResFile);
  516.     return(returnHandle);
  517. }
  518.  
  519.  
  520.  
  521. /*****************************************************************************/
  522.  
  523.  
  524.  
  525. /* GetAppResource gets a resource from the application's resource file by
  526. ** resource ID. */
  527.  
  528. #pragma segment UtilMain
  529. Handle    GetAppResource(ResType theType,short theID, OSErr *err)
  530. {
  531.     short    savedResFile;
  532.     Handle    returnHandle;
  533.  
  534.     savedResFile = CurResFile();
  535.     UseResFile(gAppResRef);
  536.     returnHandle = Get1Resource(theType, theID);
  537.     *err = ResError();
  538.     UseResFile(savedResFile);
  539.     return(returnHandle);
  540. }
  541.  
  542.  
  543.  
  544. /*****************************************************************************/
  545.  
  546.  
  547.  
  548. /* Checks for the presence of A/UX by whatever means is appropriate.  Returns
  549. ** the major version number of A/UX (i.e. 0 if A/UX is not present, 1 for
  550. ** any 1.x.x version 2 for any 2.x version, etc.
  551. **
  552. ** This code should work for all past, present and future A/UX systems. */
  553.  
  554. #define HWCfgFlags    0xB22    /* Low memory global used to check if A/UX is running */
  555.  
  556. #pragma segment UtilMain
  557. short    GetAUXVersion(void)
  558. {
  559.     long    auxVersion;
  560.     short    err;
  561.     short    *flagPtr;
  562.  
  563.     /* This code assumes the Gestalt glue checks for the presence of the _Gestalt
  564.     ** trap and does something intelligent if the trap is unavailable, i.e.
  565.     ** return unknown selector. */
  566.  
  567.     auxVersion = 0;
  568.     err = Gestalt(gestaltAUXVersion, &auxVersion);
  569.  
  570.     /* If gestaltUnknownErr or gestaltUndefSelectorErr was returned, then either
  571.     ** we weren't running on A/UX, or the _Gestalt trap is unavailable so use
  572.     ** HWCfgFlags instead.
  573.     ** All other errors are ignored (implies A/UX not present). */
  574.  
  575.     if (err == gestaltUnknownErr || err == gestaltUndefSelectorErr) {    /* Use HWCfgFlags */
  576.         flagPtr = (short *) HWCfgFlags;
  577.         if (BTstQ(*flagPtr, 9))
  578.             auxVersion = 0x100;            /* Do Have A/UX, so assume version 1.x.x */
  579.     }
  580.  
  581.     /* Now right shift auxVersion by 8 bits to get major version number. */
  582.  
  583.     auxVersion >>= 8;
  584.     return((short)auxVersion);
  585. }
  586.  
  587.  
  588.  
  589. /*****************************************************************************/
  590.  
  591.  
  592.  
  593. /* This function returns which kind of button the control is.  This does more
  594. ** than GetCVariant in that it makes sure that the control is actually a
  595. ** button.  It does this by comparing the defProc against the known defProc
  596. ** for the various button types.  For 7.0, there is only one defProc for all
  597. ** variants, but for pre-7.0, there is one defProc value for each variant.
  598. ** The method below handles either case. */
  599.  
  600. #pragma segment UtilMain
  601. short    GetButtonVariant(ControlHandle ctl)
  602. {
  603.     short            i;
  604.     Rect            dummy;
  605.     ControlHandle    dummyCtl;
  606.  
  607.     for (i = pushButProc; i <= radioButProc; ++i) {
  608.         if (!gButtonProcs[i]) {
  609.             SetRect(&dummy, 0, 0, 0, 0);
  610.             dummyCtl = NewControl((*ctl)->contrlOwner, &dummy, (ConstStr255Param)"\p",
  611.                                   false, 1, 0, 1, i, 0L);
  612.             if (dummyCtl) {
  613.                 gButtonProcs[i] = (*dummyCtl)->contrlDefProc;
  614.                 DisposeControl(dummyCtl);
  615.             }
  616.         }
  617.         if ((*ctl)->contrlDefProc == gButtonProcs[i]) return(GetCVariant(ctl));
  618.     }
  619.  
  620.     return(-1);
  621. }
  622.  
  623.  
  624.  
  625. /*****************************************************************************/
  626.  
  627.  
  628.  
  629. #pragma segment UtilMain
  630. OSErr    SimpleCanDialog(void)
  631. {
  632.     OSErr                err;
  633.     ProcessSerialNumber    cpsn, fpsn;
  634.     Boolean                procsSame;
  635.  
  636.     err = noErr;
  637.     if (gSystemVersion >= 0x0700) {
  638.         err = AEInteractWithUser(kAEDefaultTimeout, nil, nil);
  639.             /* Ask the AppleEvent Manager if we can come forward */
  640.         GetCurrentProcess(&cpsn);        /* We may have been moved to the front. */
  641.         GetFrontProcess(&fpsn);
  642.         SameProcess(&cpsn, &fpsn, &procsSame);
  643.         gInBackground = !procsSame;
  644.     }
  645.  
  646. /* Three results are possible here....
  647. **   noErr
  648. **     If the call completes with noErr, you can assume that you are
  649. **     (or have been made) the frontmost application, and you are free
  650. **     to interact with the user as much as you'd like.  Put up dialogs,
  651. **     flash alerts, whatever.
  652. **     If you were already in the foreground, AEInteractWithUser
  653. **     immediatly returns with a noErr, so you _should_ always call it.
  654. **
  655. **   errAETimeout
  656. **     If you pass a timeout value, or kAEDefaultTimeout, it is possible
  657. **     for the AEInteractWithUser call to timeout and return control to
  658. **     you before any state change has happened, you are still in the background.
  659. **     What you do at this point is a design decision you'll have to make.
  660. **     You can re-post the AEInteract call, perhaps with a larger timeout
  661. **     or kNoTimeOut, and see if you come forward this time.
  662. **     Or, you can continue on knowing that you are in the background and
  663. **     not interact at all.
  664. **
  665. **   errAENoUserInteraction
  666. **     If you get this error code back, this means that you
  667. **     MUST NOT interact with the user.  Do NOT put up any dialogs, alerts,
  668. **     or cause any other action that requires direct user intervention.
  669. **     This error code will be returned, for example, if any application
  670. **     has used the AESetInteractionAllowed call to specify no interaction,
  671. **     or if there is a pending AppleEvent that has interaction denied.
  672. **     This will also be returned if your application is being run by
  673. **     a script system, since an AppleEvent script cannot press buttons.
  674. **     By the way, if this is the case the AEinteractWithUser call has
  675. **     also not posted the notification.
  676. */
  677.  
  678.     return(err);
  679. }
  680.  
  681.  
  682.  
  683. /*****************************************************************************/
  684.  
  685.  
  686.  
  687. /* Given a dialog ID and a window pointer the dialog relates to, this function
  688. ** will center the dialog’s rectangle before showing it on the proper screen.
  689. ** This follows the Apple Human Interface Guidelines for where to place a
  690. ** centered window on the screen.  If the dialog is not closely associated with
  691. ** another window, pass a nil for the window pointer of the related window.  If
  692. ** you pass a nil, the dialog is simply displayed where the resource
  693. ** would indicate. */
  694.  
  695. #pragma segment UtilMain
  696. DialogPtr    GetCenteredDialog(short id, DialogPtr storage, WindowPtr relatedWindow, WindowPtr behind)
  697. {
  698.     DialogTHndl    dlogResource;
  699.     DialogPtr    dialog;
  700.     Boolean        oldVis;
  701.     char        hstate;
  702.     OSErr        err;
  703.     Rect        sizeInfo;
  704.  
  705.     dialog = nil;
  706.     if (!SimpleCanDialog()) {
  707.         if (dlogResource = (DialogTHndl)GetAppResource('DLOG', id, &err)) {
  708.             hstate = LockHandleHigh((Handle)dlogResource);
  709.             oldVis = (*dlogResource)->visible;
  710.             (*dlogResource)->visible = false;
  711.             if (dialog = GetNewDialog(id, storage, behind)) {
  712.                 SetRect(&sizeInfo, 0, 0, 0, 0);
  713.                 CenterWindow(dialog, relatedWindow, sizeInfo);
  714.                 if (oldVis)
  715.                     ShowWindow(dialog);
  716.             }
  717.             (*dlogResource)->visible = oldVis;
  718.             HSetState((Handle)dlogResource, hstate);
  719.         }
  720.     }
  721.     return(dialog);
  722. }
  723.  
  724.  
  725.  
  726. /*****************************************************************************/
  727.  
  728.  
  729.  
  730. /* Given a window ID and a window pointer the window relates to, this function
  731. ** will center the window’s rectangle before showing it on the proper screen.
  732. ** This follows the Apple Human Interface Guidelines for where to place a
  733. ** centered window on the screen.  If the window is not closely associated with
  734. ** another window, pass a nil for the window pointer of the related window.  If
  735. ** you pass a nil, the window is simply displayed where the resource
  736. ** would indicate. */
  737.  
  738. #pragma segment UtilMain
  739. WindowPtr    GetCenteredWindow(short id, Ptr storage, Boolean vis, WindowPtr relWindow,
  740.                               WindowPtr behind, Boolean inColor, Rect sizeInfo, long refCon)
  741. {
  742.     return(GetSomeKindOfWindow(CenterWindow, id, storage, vis, relWindow,
  743.                                behind, inColor, sizeInfo, refCon));
  744. }
  745.  
  746.  
  747.  
  748. /*****************************************************************************/
  749.  
  750.  
  751.  
  752. #pragma segment UtilMain
  753. Boolean GetCheckOrRadio(DialogPtr dlgPtr, short itemNo)
  754. {
  755.     short    iKind;
  756.     Handle    iHandle;
  757.     Rect    iRect;
  758.  
  759.     GetDItem(dlgPtr, itemNo, &iKind, &iHandle, &iRect);
  760.     return(GetCtlValue((ControlHandle)iHandle) != 0);
  761. }
  762.  
  763.  
  764.  
  765. /*****************************************************************************/
  766.  
  767.  
  768.  
  769. /* GetGestaltResult returns the result value from Gestalt for the specified
  770. ** selector.  If Gestalt returned an error GetGestaltResult returns zero.
  771. ** Use of this function is only cool if we don't care whether Gestalt returned
  772. ** an error.  In many cases you may need to know the exact Gestalt error code
  773. ** so then this function would be inappropriate.
  774. ** See GetAUXVersion for an example. */
  775.  
  776. #pragma segment UtilMain
  777. long    GetGestaltResult(OSType gestaltSelector)
  778. {
  779.     long    gestaltResult;
  780.  
  781.     if (Gestalt(gestaltSelector, &gestaltResult) == noErr)
  782.         return(gestaltResult);
  783.     else
  784.         return(0);
  785. }
  786.  
  787.  
  788.  
  789. /*****************************************************************************/
  790.  
  791.  
  792.  
  793. /* Get the global coordinates of the mouse.  When you call OSEventAvail it will
  794. ** return either a pending event or a null event.  In either case, the where
  795. ** field of the event record will contain the current position of the mouse in
  796. ** global coordinates and the modifiers field will reflect the current state of
  797. ** the modifiers.  Another way to get the global coordinates is to call
  798. ** GetMouse and LocalToGlobal, but that requires being sure that thePort is set
  799. ** to a valid port. */
  800.  
  801. #pragma segment UtilMain
  802. Point    GetGlobalMouse(void)
  803. {
  804.     EventRecord    event;
  805.  
  806.     OSEventAvail(kNoEvents, &event);    /* we aren’t interested in any events */
  807.     return(event.where);                /* just the mouse position */
  808. }
  809.  
  810.  
  811.  
  812. /*****************************************************************************/
  813.  
  814.  
  815.  
  816. /* Given a window, this will return the top left point of the window’s port in
  817. ** global coordinates.  Something this doesn’t include is the window’s drag
  818. ** region (or title bar).  This returns the top left point of the window’s
  819. ** content area only. */
  820.  
  821. #pragma segment UtilMain
  822. Point    GetGlobalTopLeft(WindowPtr window)
  823. {
  824.     GrafPtr    oldPort;
  825.     Point    globalPt;
  826.  
  827.     GetPort(&oldPort);
  828.     SetPort(window);
  829.     globalPt = TopLeft(window->portRect);
  830.     LocalToGlobal(&globalPt);
  831.     SetPort(oldPort);
  832.     return(globalPt);
  833. }
  834.  
  835.  
  836.  
  837. /*****************************************************************************/
  838.  
  839.  
  840.  
  841. /* Return the amount of free space on the volume in KBytes. -1 is returned as
  842. ** the size if there is an error. */
  843.  
  844. #pragma segment UtilMain
  845. long    GetKFreeSpace(short vRefNum)
  846. {
  847.     HParamBlockRec    pb;
  848.     OSErr            err;
  849.  
  850.     pb.volumeParam.ioNamePtr = nil;            /* we don't care about the name */
  851.     pb.volumeParam.ioVRefNum = vRefNum;
  852.     pb.volumeParam.ioVolIndex = 0;            /* use ioVRefNum only */
  853.     err = PBHGetVInfo(&pb, false);
  854.  
  855.     if (err == noErr)
  856.         return((pb.volumeParam.ioVFrBlk * pb.volumeParam.ioVAlBlkSiz) / 1024);
  857.     else
  858.         return(-1);
  859. }
  860.  
  861.  
  862.  
  863. /*****************************************************************************/
  864.  
  865.  
  866.  
  867. #pragma segment UtilMain
  868. Rect    GetMainScreenRect(void)
  869. {
  870.     GDHandle    mainDevice;
  871.     GrafPtr        mainPort;
  872.  
  873.     if (gQDVersion > kQDOriginal) {
  874.         mainDevice = GetMainDevice();
  875.         return((*mainDevice)->gdRect);
  876.     }
  877.     else {
  878.         GetWMgrPort(&mainPort);
  879.         return(mainPort->portRect);
  880.     }
  881. }
  882.  
  883.  
  884.  
  885. /*****************************************************************************/
  886.  
  887.  
  888.  
  889. /* Find the greatest overlap device for the given global rectangle. */
  890.  
  891. #pragma segment UtilMain
  892. GDHandle    GetRectDevice(Rect globalRect)
  893. {
  894.     long        area, maxArea;
  895.     GDHandle    device, deviceToReturn;
  896.     Rect        intersection;
  897.  
  898.     deviceToReturn = GetMainDevice();            /* Use as default choice. */
  899.     maxArea = 0;
  900.  
  901.     for (device = GetDeviceList(); device; device = GetNextDevice(device)) {
  902.         if (TestDeviceAttribute(device, screenDevice)
  903.           && TestDeviceAttribute(device, screenActive)
  904.           && SectRect(&globalRect, &((*device)->gdRect), &intersection)) {
  905.             area = ((long)(intersection.right - intersection.left)) *
  906.                    ((long)(intersection.bottom - intersection.top));
  907.             if (area > maxArea) {
  908.                 deviceToReturn = device;
  909.                 maxArea = area;
  910.             }
  911.         }
  912.     }
  913.     return(deviceToReturn);
  914. }
  915.  
  916.  
  917.  
  918. /*****************************************************************************/
  919.  
  920.  
  921.  
  922. /* Find the rect of the greatest overlap device for the given global rect. */
  923.  
  924. #pragma segment UtilMain
  925. Rect    GetRectDeviceRect(Rect globalRect)
  926. {
  927.     if (gQDVersion > kQDOriginal)
  928.         return((*GetRectDevice(globalRect))->gdRect);
  929.     else
  930.         return(GetMainScreenRect());
  931. }
  932.  
  933.  
  934.  
  935. /*****************************************************************************/
  936.  
  937.  
  938.  
  939. /* Given a window positioning procedure pointer, a window ID and a window
  940. ** pointer the window relates to, this function open a new window by either
  941. ** a NewCWindow or a NewWindow call, depending on the value of inColor.  The
  942. ** window will be opened invisible, independent of what the resource says.
  943. ** Once the window is opened successfully, the positioning procedure is
  944. ** called.  The positioning procedure is passed a pointer to the just-opened
  945. ** invisible window and a pointer to the related window.  It is up to the
  946. ** positioning procedure to move the invisible window to the correct location
  947. ** on the correct device.  Once the positioning procedure returns, the window
  948. ** will be made visible if so indicated by the resource. */
  949.  
  950. #pragma segment UtilMain
  951. WindowPtr    GetSomeKindOfWindow(PositionWndProcPtr whatKind, short windID, Ptr storage,
  952.                                 Boolean vis, WindowPtr relatedWindow, WindowPtr behind,
  953.                                 Boolean inColor, Rect sizeInfo, long refCon)
  954. {
  955.     WindowTHndl        windowResource;
  956.     WindowTemplate    wt;                /* Window template. */
  957.     WindowPtr        window;
  958.     PaletteHandle    wpalette;
  959.     OSErr            err;
  960.  
  961.     if (gQDVersion == kQDOriginal)
  962.         inColor = false;
  963.  
  964.     window = nil;        /* Assume we will fail.  (Good attitude.) */
  965.  
  966.     if (!storage)
  967.         storage = NewPtr(sizeof(WindowRecord));
  968.  
  969.     if (storage) {            /* If we have memory for the window record... */
  970.  
  971.         if (windowResource = (WindowTHndl)GetAppResource('WIND', windID, &err)) {
  972.             /* If we can load the window resource... */
  973.  
  974.             wt = **windowResource;        /* Make local copy of resource. */
  975.  
  976.             window = (inColor ? NewCWindow(storage, &wt.boundsRect,
  977.                                            wt.title, false, wt.procID,
  978.                                            behind, wt.goAwayFlag, wt.refCon)
  979.                                : NewWindow(storage, &wt.boundsRect, wt.title,
  980.                                            false, wt.procID,
  981.                                            behind, wt.goAwayFlag, wt.refCon));
  982.                 /* Open either a regular or color window. */
  983.  
  984.             if (window) {        /* If we were able to open a window... */
  985.                 if (inColor)
  986.                     if (wpalette = GetNewPalette(windID))
  987.                         SetPalette(window, wpalette, true);
  988.  
  989.                 SetWRefCon(window, refCon);
  990.                 if (whatKind)
  991.                     (*whatKind)(window, relatedWindow, sizeInfo);
  992.                         /* Call the designated window positioning procedure. */
  993.  
  994.                 if (vis)
  995.                     ShowWindow(window);
  996.                         /* If caller says window should be visible, make it so. */
  997.             }
  998.         }
  999.         if (!window)
  1000.             DisposPtr(storage);
  1001.                 /* If we failed, then get rid of window record memory. */
  1002.     }
  1003.  
  1004.     return(window);
  1005. }
  1006.  
  1007.  
  1008.  
  1009. /*****************************************************************************/
  1010.  
  1011.  
  1012.  
  1013. /* Given a window ID and a window pointer the window relates to, this function
  1014. ** will stagger the window’s rectangle before showing it on the proper screen.
  1015. ** This follows the Apple Human Interface Guidelines for where to place a
  1016. ** staggered window on the screen.  If the window is not closely associated
  1017. ** with another window, pass a nil for the window pointer of the related
  1018. ** window.  If you pass a nil, the window is simply displayed where the
  1019. ** resource would indicate. */
  1020.  
  1021. #pragma segment UtilMain
  1022. WindowPtr    GetStaggeredWindow(short id, Ptr storage, Boolean vis, WindowPtr relWindow,
  1023.                                WindowPtr behind, Boolean inColor, Rect sizeInfo, long refCon)
  1024. {
  1025.     return(GetSomeKindOfWindow(StaggerWindow, id, storage, vis, relWindow,
  1026.                                behind, inColor, sizeInfo, refCon));
  1027. }
  1028.  
  1029.  
  1030.  
  1031. /*****************************************************************************/
  1032.  
  1033.  
  1034.  
  1035. /*    Check the bits of a trap number to determine its type. */
  1036.  
  1037. #pragma segment UtilMain
  1038. TrapType    GetTrapType(short theTrap)
  1039. {
  1040.     /* OS traps start with A0, Tool with A8 or AA. */
  1041.     if ((theTrap & 0x0800) == 0)                    /* per D.A. */
  1042.         return(OSTrap);
  1043.     else
  1044.         return(ToolTrap);
  1045. }
  1046.  
  1047.  
  1048.  
  1049. /*****************************************************************************/
  1050.  
  1051.  
  1052.  
  1053. /* Given a window pointer, return the global rectangle that encloses the
  1054. ** content area of the window. */
  1055.  
  1056. #pragma segment UtilMain
  1057. Rect    GetWindowContentRect(WindowPtr window)
  1058. {
  1059.     WindowPtr    oldPort;
  1060.     Rect        contentRect;
  1061.  
  1062.     SetRect(&contentRect, 0, 0, 0, 0);
  1063.     if (window) {
  1064.         GetPort(&oldPort);
  1065.         SetPort(window);
  1066.         contentRect = window->portRect;
  1067.         LocalToGlobalRect(&contentRect);
  1068.         SetPort(oldPort);
  1069.     }
  1070.  
  1071.     return(contentRect);
  1072. }
  1073.  
  1074.  
  1075.  
  1076. /*****************************************************************************/
  1077.  
  1078.  
  1079.  
  1080. /* This procedure counts the number of windows in the application plane.
  1081. ** You have the choices of also including DAs and invisible windows in
  1082. ** this count. */
  1083.  
  1084. #pragma segment UtilMain
  1085. short    GetWindowCount(Boolean includeDAs, Boolean includeDLOGs, Boolean includeInvisibles)
  1086. {
  1087.     WindowPeek    window;
  1088.     short        count;
  1089.  
  1090. #ifdef __SYSEQU__
  1091.     for (count = 0, window = *(WindowPeek *)WindowList;
  1092. #else
  1093.     for (count = 0, window = WindowList;
  1094. #endif
  1095.          (window != nil); window = window->nextWindow) {
  1096.  
  1097.         if ((window->windowKind < 0) && (!includeDAs)) continue;
  1098.         if ((window->windowKind < userKind) && (!includeDLOGs)) continue;
  1099.         if ((window->visible) || (includeInvisibles))
  1100.             count++;
  1101.     }
  1102.     return(count);
  1103. }
  1104.  
  1105.  
  1106.  
  1107. /*****************************************************************************/
  1108.  
  1109.  
  1110.  
  1111. /* Find the greatest overlap device for the given window. */
  1112.  
  1113. #pragma segment UtilMain
  1114. GDHandle    GetWindowDevice(WindowPtr window)
  1115. {
  1116.     return(GetRectDevice(GetWindowStructureRect(window)));
  1117. }
  1118.  
  1119.  
  1120.  
  1121. /*****************************************************************************/
  1122.  
  1123.  
  1124.  
  1125. /* Given a window pointer, find the device that contains most of the window
  1126. ** and return the device's bounding rectangle. */
  1127.  
  1128. #pragma segment UtilMain
  1129. Rect    GetWindowDeviceRect(WindowPtr window)
  1130. {
  1131.     if (gQDVersion > kQDOriginal)
  1132.         return((*GetWindowDevice(window))->gdRect);
  1133.     else
  1134.         return(GetMainScreenRect());
  1135. }
  1136.  
  1137.  
  1138.  
  1139. /*****************************************************************************/
  1140.  
  1141.  
  1142.  
  1143. /* Given a window pointer, find the device that contains most of the window
  1144. ** and return the device's bounding rectangle.  If this device is the main
  1145. ** device, then remove the menubar area from the rectangle. */
  1146.  
  1147. #pragma segment UtilMain
  1148. Rect    GetWindowDeviceRectNMB(WindowPtr window)
  1149. {
  1150.     Rect    deviceRect, tempRect;
  1151.  
  1152.     SetRect(&deviceRect, 0, 0, 0, 0);
  1153.  
  1154.     if (window) {
  1155.  
  1156.         deviceRect = GetWindowDeviceRect(window);
  1157.         tempRect = GetMainScreenRect();
  1158.         if (EqualRect(&deviceRect, &tempRect))
  1159.             deviceRect.top += GetMBarHeight();
  1160.     }
  1161.  
  1162.     return(deviceRect);
  1163. }
  1164.  
  1165.  
  1166.  
  1167. /*****************************************************************************/
  1168.  
  1169.  
  1170.  
  1171. /* This procedure is used to get the rectangle that surrounds the entire
  1172. ** structure of a window.  This is true whether or not the window is visible.
  1173. ** If the window is visible, then it is a simple matter of using the bounding
  1174. ** rectangle of the structure region.  If the window is invisible, then the
  1175. ** strucRgn is not correct.  To make it correct, then window has to be moved
  1176. ** way off the screen and then made visible.  This generates a valid strucRgn,
  1177. ** although it is valid for the position that is way off the screen.  It still
  1178. ** needs to be offset back into the original position.  Once the bounding
  1179. ** rectangle for the strucRgn is obtained, the window can then be hidden again
  1180. ** and moved back to its correct location.  Note that ShowHide is used,
  1181. ** instead of ShowWindow and HideWindow.  HideWindow can change the plane of
  1182. ** the window.  Also, ShowHide does not affect the hiliting of windows.
  1183. ** Note that using ShowHide to make the window visible has the unfortunate
  1184. ** side-effect of changing the userState rect.  Since we make the window
  1185. ** invisible prior to moving it back, userState gets left funky.  Due to this,
  1186. ** we have to cache it prior to doing the ShowHide games. */
  1187.  
  1188. #pragma segment UtilMain
  1189. Rect    GetWindowStructureRect(WindowPtr window)
  1190. {
  1191. #define kOffscreenLoc 0x4000
  1192.  
  1193.     GrafPtr    oldPort;
  1194.     Rect    structureRect, userState;
  1195.     Point    windowLoc;
  1196.  
  1197.     SetRect(&structureRect, 0, 0, 0, 0);
  1198.  
  1199.     if (window) {
  1200.  
  1201.         if (((WindowPeek)window)->visible)
  1202.             structureRect = (*(((WindowPeek)window)->strucRgn))->rgnBBox;
  1203.  
  1204.         else {
  1205.             GetPort(&oldPort);
  1206.             SetPort(window);
  1207.             windowLoc = GetGlobalTopLeft(window);
  1208.             userState = (*(WStateDataHandle)(((WindowPeek)window)->dataHandle))->userState;
  1209.             MoveWindow(window, kOffscreenLoc, kOffscreenLoc, false);
  1210.             ShowHide(window, true);
  1211.             structureRect = (*(((WindowPeek)window)->strucRgn))->rgnBBox;
  1212.             ShowHide(window, false);
  1213.             MoveWindow(window, windowLoc.h, windowLoc.v, false);
  1214.             (*(WStateDataHandle)(((WindowPeek)window)->dataHandle))->userState = userState;
  1215.             SetPort(oldPort);
  1216.             OffsetRect(&structureRect, windowLoc.h - kOffscreenLoc, windowLoc.v - kOffscreenLoc);
  1217.         }
  1218.     }
  1219.  
  1220.     return(structureRect);
  1221. }
  1222.  
  1223.  
  1224.  
  1225. /*****************************************************************************/
  1226.  
  1227.  
  1228.  
  1229. #pragma segment UtilMain
  1230. void    GlobalToLocalRect(Rect *aRect)
  1231. {
  1232.     GlobalToLocal(&TopLeft(*aRect));
  1233.     GlobalToLocal(&BotRight(*aRect));
  1234. }
  1235.  
  1236.  
  1237.  
  1238. /*****************************************************************************/
  1239.  
  1240.  
  1241.  
  1242. #pragma segment UtilMain
  1243. void    InitToolBox(void)
  1244. {
  1245.     InitGraf((Ptr) &QD(thePort));
  1246.     InitFonts();
  1247.     InitWindows();
  1248.     InitMenus();
  1249.     TEInit();
  1250.     InitDialogs(nil);
  1251.     InitCursor();
  1252. }
  1253.  
  1254.  
  1255.  
  1256. /*****************************************************************************/
  1257.  
  1258.  
  1259.  
  1260. /* GetSystemInfo sets up some global variables for use by the utilities
  1261. ** package and your application.  If you call StandardInitialization, you
  1262. ** don't need to call this, as it will do it for you. */
  1263.  
  1264. #pragma segment UtilMain
  1265. void    GetSystemInfo(void)
  1266. {
  1267.     Handle            apParam;
  1268.     Handle            bndlResource;
  1269.     OSErr            err;
  1270.     short            ignoreRefNum;
  1271.  
  1272.     if (!gHaveSystemInfo) {
  1273.  
  1274.         /* Init all the Gestalt variables */
  1275.         gMachineType   = GetGestaltResult(gestaltMachineType);
  1276.         gSystemVersion = GetGestaltResult(gestaltSystemVersion);
  1277.         gProcessorType = GetGestaltResult(gestaltProcessorType);
  1278.  
  1279.         /* We only concern ourselves with there being an FPU, not which type it is. */
  1280.         gHasFPU = (GetGestaltResult(gestaltFPUType) != gestaltNoFPU);
  1281.  
  1282.         /* We only concern ourselves with the major QD version number
  1283.         ** 0 for original QD, 1 for 8-bit color QD, and 2 for 32-bit QD. */
  1284.  
  1285.         gQDVersion = (GetGestaltResult(gestaltQuickdrawVersion) >> 8) & 0xFF;
  1286.         gKeyboardType = GetGestaltResult(gestaltKeyboardType);
  1287.  
  1288.         if (!OpenDriver("\p.MPP", &ignoreRefNum))
  1289.             gAppleTalkVersion = GetGestaltResult(gestaltAppleTalkVersion);
  1290.                 /* Under system 6, the driver isn't necessarily open, so open it for sure.
  1291.                 ** If the driver isn't opened, then the gestalt selector isn't installed,
  1292.                 ** and therefore returns 0, which isn't really the case. */
  1293.  
  1294.         /* We only concern ourselves with there being an PMMU, not which type it is. */
  1295.         gHasPMMU = GetGestaltResult(gestaltMMUType) >= gestalt68851;
  1296.         gAUXVersion = GetAUXVersion();
  1297.  
  1298.         gHasWaitNextEvent = TrapExists(_WaitNextEvent);
  1299.         gInBackground = false;
  1300.  
  1301.         GetAppParms(gAppName, &gAppResRef, &apParam);
  1302. #ifdef THINK_C
  1303.         gAppResRef = CurResFile();            /* returns refNum of .rsrc file */
  1304.             /* 10/16/90 pvh/MacDTS
  1305.             ** With GetAppParams(), THINK C in project mode returns the project resource
  1306.             ** file AND NOT the .rsrc file, which is what one really wants (trust me).
  1307.             ** If THINK is present we will return CurResFile() which will be the .rsrc
  1308.             ** file instead.  The name will still be the project name in project mode,
  1309.             ** so be aware of that. */
  1310. #endif
  1311.  
  1312.         bndlResource = GetAppIndResource('BNDL', 1, &err);
  1313.         if (bndlResource)
  1314.             gSignature = *(OSType *)(*bndlResource);
  1315.  
  1316.         gHaveSystemInfo = true;
  1317.     }
  1318. }
  1319.  
  1320.  
  1321.  
  1322. /*****************************************************************************/
  1323.  
  1324.  
  1325.  
  1326. /* Check to see if a window belongs to the application.  If the window pointer
  1327. ** passed was nil, then it could not be an application window.  WindowKinds
  1328. ** that are negative belong to the system and windowKinds less than userKind
  1329. ** are reserved by Apple except for windowKinds equal to dialogKind, which
  1330. ** mean it is a dialog. */
  1331.  
  1332. #pragma segment UtilMain
  1333. Boolean    IsAppWindow(WindowPtr window)
  1334. {
  1335.     if (window) return(((WindowPeek)window)->windowKind >= userKind);
  1336.     else        return(false);
  1337. }
  1338.  
  1339.  
  1340.  
  1341. /*****************************************************************************/
  1342.  
  1343.  
  1344.  
  1345. /* Check to see if a window belongs to a desk accessory. */
  1346.  
  1347. #pragma segment UtilMain
  1348. Boolean    IsDAWindow(WindowPtr window)
  1349. {
  1350.     if (window)    /* DA windows have negative windowKinds */
  1351.         return(((WindowPeek) window)->windowKind < 0);
  1352.     else
  1353.         return(false);
  1354. }
  1355.  
  1356.  
  1357.  
  1358. /*****************************************************************************/
  1359.  
  1360.  
  1361.  
  1362. #pragma segment UtilMain
  1363. Boolean    IsScrollBar(ControlHandle ctl)
  1364. {
  1365.     Rect            dummy;
  1366.     ControlHandle    dummyCtl;
  1367.  
  1368.     if (!ctl) return(false);
  1369.  
  1370.     if (!gScrollProc) {
  1371.         SetRect(&dummy, 0, 0, 16, 100);
  1372.         dummyCtl = NewControl((*ctl)->contrlOwner, &dummy, (ConstStr255Param)"\p",
  1373.                               false, 1, 0, 1, scrollBarProc, 0L);
  1374.         if (dummyCtl) {
  1375.             gScrollProc = (*dummyCtl)->contrlDefProc;
  1376.             DisposeControl(dummyCtl);
  1377.         }
  1378.     }
  1379.  
  1380.     return((*ctl)->contrlDefProc == gScrollProc);
  1381. }
  1382.  
  1383.  
  1384.  
  1385. /*****************************************************************************/
  1386.  
  1387.  
  1388.  
  1389. #pragma segment UtilMain
  1390. void    LocalToGlobalRect(Rect *aRect)
  1391. {
  1392.     LocalToGlobal(&TopLeft(*aRect));
  1393.     LocalToGlobal(&BotRight(*aRect));
  1394. }
  1395.  
  1396.  
  1397.  
  1398. /*****************************************************************************/
  1399.  
  1400.  
  1401.  
  1402. #pragma segment UtilMain
  1403. char    LockHandleHigh(Handle theHandle)
  1404. {
  1405.     char    hstate;
  1406.  
  1407.     hstate = HGetState(theHandle);
  1408.     MoveHHi(theHandle);
  1409.     HLock(theHandle);
  1410.     return(hstate);
  1411. }
  1412.  
  1413.  
  1414.  
  1415. /*****************************************************************************/
  1416.  
  1417.  
  1418.  
  1419. /* InitGraf is always implemented (trap $A86E).  If the trap table is big
  1420. ** enough, trap $AA6E will always point to either Unimplemented or some other
  1421. ** trap, but will never be the same as InitGraf.  Thus, you can check the size
  1422. ** of the trap table by asking if the address of trap $A86E is the same as
  1423. ** $AA6E. */
  1424.  
  1425. #pragma segment UtilMain
  1426. short    NumToolboxTraps(void)
  1427. {
  1428.     if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  1429.         return(0x200);
  1430.     else
  1431.         return(0x400);
  1432. }
  1433.  
  1434.  
  1435.  
  1436. /*****************************************************************************/
  1437.  
  1438.  
  1439.  
  1440. /* Given any control handle, this will draw an outline around it.  This is used
  1441. ** for the default button of a window.  The extra nice feature here is that
  1442. ** I’ll erase the outline for buttons that are inactive.  Seems like there
  1443. ** should be a Toolbox call for getting a control’s hilite state.  Since there
  1444. ** isn’t, I have to look into the control record myself.  This should be called
  1445. ** for update and activate events.
  1446. **
  1447. ** The method for determining the oval diameters for the roundrect is a little
  1448. ** different than that recommended by Inside Mac. IM I-407 suggests that you
  1449. ** use a hardcoded (16,16) for the diameters.  However, this only looks good
  1450. ** for small roundrects.  For larger ones, the outline doesn’t follow the inner
  1451. ** roundrect because the CDEF for simple buttons doesn’t use (16,16).  Instead,
  1452. ** it uses half the height of the button as the diameter.  By using this
  1453. ** formula, too, our outlines look better. */
  1454.  
  1455. #pragma segment UtilMain
  1456. void    OutlineControl(ControlHandle button)
  1457. {
  1458.     WindowPtr    oldPort;
  1459.     Rect        theRect;
  1460.     PenState    curPen;
  1461.     short        buttonOval;
  1462.  
  1463.     if (button) {
  1464.         GetPort(&oldPort);
  1465.         SetPort((*button)->contrlOwner);
  1466.         GetPenState(&curPen);
  1467.         PenNormal();
  1468.         theRect = (*button)->contrlRect;
  1469.         InsetRect(&theRect, kButtonFrameInset, kButtonFrameInset);
  1470.         buttonOval = (theRect.bottom - theRect.top) / 2 + 2;
  1471.  
  1472.         PenPat((*button)->contrlHilite == kCntlActivate ? &QD(black) : &QD(gray));
  1473.  
  1474.         PenSize(kButtonFrameSize, kButtonFrameSize);
  1475.         FrameRoundRect(&theRect, buttonOval, buttonOval);
  1476.         SetPenState(&curPen);
  1477.         SetPort(oldPort);
  1478.     }
  1479. }
  1480.  
  1481.  
  1482.  
  1483. /*****************************************************************************/
  1484.  
  1485.  
  1486.  
  1487. #pragma segment UtilMain
  1488. void    OutlineDialogItem(DialogPtr dlgPtr, short item)
  1489. {
  1490.     short    iKind;
  1491.     Handle    iHandle;
  1492.     Rect    iRect;
  1493.  
  1494.     GetDItem(dlgPtr, item, &iKind, &iHandle, &iRect);
  1495.     OutlineControl((ControlHandle) iHandle);
  1496. }
  1497.  
  1498.  
  1499.  
  1500. /*****************************************************************************/
  1501.  
  1502.  
  1503.  
  1504. /* Given two rectangles, this function positions the second within the first
  1505. ** one so that it maintains the spacing specified by the horzRatio and
  1506. ** vertRatio parameters.  In other words, to center an inner rectangle
  1507. ** hoizontally, but have its center be 1/3 from the top of the outer rectangle,
  1508. ** call this function with horzRatio = FixRatio(1, 2), vertRatio =
  1509. ** FixRatio(1, 3).  We use Fixed rather than floating point to avoid
  1510. ** complications when mixing MC68881/non-MC68881 versions of Utilities. */
  1511.  
  1512. #pragma segment UtilMain
  1513. void    PositionRectInRect(Rect outerRect, Rect *innerRect, Fixed horzRatio, Fixed vertRatio)
  1514. {
  1515.     short    outerRectHeight;
  1516.     short    outerRectWidth;
  1517.     short    innerRectHeight;
  1518.     short    innerRectWidth;
  1519.     short    yLocation;
  1520.     short    xLocation;
  1521.  
  1522.     outerRectHeight = outerRect.bottom - outerRect.top;
  1523.     outerRectWidth = outerRect.right - outerRect.left;
  1524.  
  1525.     innerRectHeight = innerRect->bottom - innerRect->top;
  1526.     innerRectWidth = innerRect->right - innerRect->left;
  1527.         yLocation = Fix2Long(FixMul(Long2Fix(outerRectHeight - innerRectHeight), vertRatio))
  1528.             + outerRect.top;
  1529.         xLocation = Fix2Long(FixMul(Long2Fix(outerRectWidth - innerRectWidth), horzRatio))
  1530.             + outerRect.left;
  1531.  
  1532.     innerRect->top = yLocation;
  1533.     innerRect->left = xLocation;
  1534.     innerRect->bottom = yLocation + innerRectHeight;
  1535.     innerRect->right = xLocation + innerRectWidth;
  1536. }
  1537.  
  1538.  
  1539.  
  1540. /*****************************************************************************/
  1541.  
  1542.  
  1543.  
  1544. #pragma segment UtilMain
  1545. void    PullApplicationToFront(void)
  1546. {
  1547. #define kBroughtToFront 3
  1548.  
  1549.     EventRecord event;
  1550.     short        count;
  1551.  
  1552.     for (count = 1; count <= kBroughtToFront; count++)
  1553.         EventAvail(everyEvent, &event);
  1554. }
  1555.  
  1556.  
  1557.  
  1558. /*****************************************************************************/
  1559.  
  1560.  
  1561.  
  1562. /* Given the button control handle, this will cause the button to look as if it
  1563. ** has been clicked in.  This is nice to do for the user if they type return or
  1564. ** enter to select the default item. */
  1565.  
  1566. #pragma segment UtilMain
  1567. void    SelectButton(ControlHandle button)
  1568. {
  1569.     long    finalTicks;
  1570.  
  1571.     HiliteControl(button, kSelect);
  1572.     Delay(kDelayTime, &finalTicks);
  1573.     HiliteControl(button, kDeselect);
  1574. }
  1575.  
  1576.  
  1577.  
  1578. /*****************************************************************************/
  1579.  
  1580.  
  1581.  
  1582. /* Handy function for setting the value of a radio button.  Given a dialog
  1583. ** pointer, and item number, and a state, this function will take care of the
  1584. ** rest. */
  1585.  
  1586. #pragma segment UtilMain
  1587. void    SetCheckOrRadioButton(DialogPtr dlgPtr, short itemNo, short state)
  1588. {
  1589.     short    iKind;
  1590.     Handle    iHandle;
  1591.     Rect    iRect;
  1592.  
  1593.     GetDItem(dlgPtr, itemNo, &iKind, &iHandle, &iRect);
  1594.     SetCtlValue((ControlHandle) iHandle, state);
  1595. }
  1596.  
  1597.  
  1598.  
  1599. /*****************************************************************************/
  1600.  
  1601.  
  1602.  
  1603. /* This algorithm for staggering windows does quite a good job.  It also is
  1604. ** quite gnarly.  Here's the deal:
  1605. ** There are pre-designated positions that we will try when positioning a
  1606. ** window.  These slots will be tried from the upper-left corner towards the
  1607. ** lower-right corner.  If there are other windows in that slot, then we will
  1608. ** consider that slot taken, and proceed to the next slot.  A slot is
  1609. ** determined to be taken by checking a point with a slop area.  This slop
  1610. ** area is diamond-shaped, not simply rectangular.  If there is no other
  1611. ** visible window with an upper-left corner within the slopt diamond, then
  1612. ** we are allowed to position our window there.
  1613. ** The above rule holds true unless this forces the window to be partly
  1614. ** off the screen.  If the window ends up partly off the screen, then we try
  1615. ** a new diagonal just below the first diagonal we tried.  We keep trying
  1616. ** lower and lower diagonals until we find a spot for the window, or the
  1617. ** diagonal doesn't fit on the screen at all.  If the diagonal doesn't fit,
  1618. ** then we try diagonals to the right of the first diagonal.  If even this
  1619. ** doesn't work, then we give up and put the window in the original spot
  1620. ** we tried. */
  1621.  
  1622. #pragma segment UtilMain
  1623. Rect    StaggerWindow(WindowPtr window, WindowPtr relatedWindow, Rect sizeInfo)
  1624. {
  1625.     WindowPtr    whichDevice, staggerFromWindow;
  1626.     Rect        deviceRect, oldWindowRect, newWindowRect, slot1;
  1627.     Rect        testRect, contentRect, staggerFromRect;
  1628.     Point        delta, absdelta;
  1629.     Boolean        contained, vertTry;
  1630.     short        diamondSize, diagNum, tryNum, h, v, hh, vv;
  1631.  
  1632.     if (!(whichDevice = relatedWindow))
  1633.         whichDevice = window;
  1634.             /* If we have a window to stagger from, use the device for that window,
  1635.             ** else use the device for the window that is getting staggered. */
  1636.  
  1637.     deviceRect = GetWindowDeviceRectNMB(whichDevice);
  1638.         /* We now have the rect of the device we want to stagger within. */
  1639.  
  1640.     contentRect = GetWindowContentRect(window);        /* Get where the window is now. */
  1641.     h = hh = contentRect.right  - contentRect.left;
  1642.     v = vv = contentRect.bottom - contentRect.top;
  1643.     if (sizeInfo.left)
  1644.         if (h < sizeInfo.left)
  1645.             h = sizeInfo.left;
  1646.     if (sizeInfo.right)
  1647.         if (h > sizeInfo.right)
  1648.             h = sizeInfo.right;
  1649.     if (sizeInfo.top)
  1650.         if (v < sizeInfo.top)
  1651.             v = sizeInfo.top;
  1652.     if (sizeInfo.bottom)
  1653.         if (v > sizeInfo.bottom)
  1654.             v = sizeInfo.bottom;
  1655.     contentRect.right  = contentRect.left + h;
  1656.     contentRect.bottom = contentRect.top  + v;
  1657.  
  1658.     oldWindowRect = GetWindowStructureRect(window);
  1659.  
  1660.     newWindowRect.top    = deviceRect.top  + kStartPtV;
  1661.     newWindowRect.left   = deviceRect.left + kStartPtH;
  1662.     newWindowRect.bottom = newWindowRect.top  + oldWindowRect.bottom - oldWindowRect.top;
  1663.     newWindowRect.right  = newWindowRect.left + oldWindowRect.right  - oldWindowRect.left;
  1664.     newWindowRect.right  += (h - hh);
  1665.     newWindowRect.bottom += (v - vv);
  1666.         /* We now have a new rect for the first window position slot. */
  1667.  
  1668.     slot1 = newWindowRect;
  1669.         /* We keep this slot in case we find no acceptable slots.  If we
  1670.         ** don't find an acceptable one, we will use this one anyway. */
  1671.  
  1672.     diamondSize = (kStaggerH < kStaggerV) ? kStaggerH : kStaggerV;
  1673.     for (diagNum = 0, vertTry = true;;) {
  1674.         for (tryNum = 0;; ++tryNum) {
  1675.  
  1676.             SectRect(&newWindowRect, &deviceRect, &testRect);
  1677.             if (!(contained = EqualRect(&newWindowRect, &testRect))) break;
  1678.                 /* Break if the slot we are testing went off the device. */
  1679.  
  1680.             for (staggerFromWindow = FrontWindow(); staggerFromWindow;
  1681.                  staggerFromWindow = (WindowPtr)((WindowPeek)staggerFromWindow)->nextWindow) {
  1682.                 if (!((WindowPeek)staggerFromWindow)->visible) continue;
  1683.                     /* This window is invisible.  Staggering from an invisible
  1684.                     ** window is going to confuse the user, so don't do it. */
  1685.  
  1686.                 testRect = GetWindowDeviceRectNMB(staggerFromWindow);
  1687.                 if (!EqualRect(&testRect, &deviceRect)) continue;
  1688.                     /* This window doesn't belong to the device we are trying to
  1689.                     ** stagger on, so skip it and go to the next window. */
  1690.  
  1691.                 staggerFromRect = GetWindowStructureRect(staggerFromWindow);
  1692.                 delta.v = staggerFromRect.top  - newWindowRect.top;
  1693.                 delta.h = staggerFromRect.left - newWindowRect.left;
  1694.                 if ((absdelta.v = delta.v) < 0)
  1695.                     absdelta.v = -delta.v;
  1696.                 if ((absdelta.h = delta.h) < 0)
  1697.                     absdelta.h = -delta.h;
  1698.                 if ((absdelta.h + absdelta.v) < diamondSize) {
  1699.                     if ((delta.h + delta.v) > 0)
  1700.                         OffsetRect(&newWindowRect, delta.h, delta.v);
  1701.                             /* If the window that took our slot is closer to
  1702.                             ** the lower-right corner than we are, then use
  1703.                             ** this window's location as the basis for the
  1704.                             ** slots from now on.  This will align new windows
  1705.                             ** with previous windows that are not gridded to
  1706.                             ** the default slot positions.  The check for > 0
  1707.                             ** is necessary to prevent bouncing between two
  1708.                             ** existing windows.  This check guarantees that
  1709.                             ** we are progressing with the evaluation. */
  1710.                     break;
  1711.                         /* Break because this slot is already used. */
  1712.                 }
  1713.             }
  1714.  
  1715.             if (!staggerFromWindow) break;
  1716.                 /* If the window pointer is nil, then we tried all the windows
  1717.                 ** and none of them occupied this slot.  This means that the
  1718.                 ** slot is available for the new window. */
  1719.  
  1720.                 OffsetRect(&newWindowRect, kStaggerH, kStaggerV);
  1721.                 /* Since this slot was taken, try the next slot and go through
  1722.                 ** the window list again. */
  1723.         }
  1724.  
  1725.         if (contained) break;
  1726.         newWindowRect = slot1;
  1727.         if (!tryNum) {
  1728.             if (!vertTry) break;        /* Nothing works.  No spots at all. */
  1729.             vertTry = false;            /* Try across for the next pass. */
  1730.             diagNum = 0;
  1731.         }
  1732.         ++diagNum;
  1733.         if (vertTry)
  1734.             OffsetRect(&newWindowRect, 0, diagNum * kStaggerV);
  1735.         else
  1736.             OffsetRect(&newWindowRect, diagNum * kStaggerH, 0);
  1737.     }
  1738.  
  1739.     OffsetRect(&contentRect, newWindowRect.left - oldWindowRect.left,
  1740.                             newWindowRect.top  - oldWindowRect.top);
  1741.         /* Calculate the new content rect. */
  1742.  
  1743.     MoveWindow(window, contentRect.left, contentRect.top, false);
  1744.         /* Move the window to the new location. */
  1745.  
  1746.     oldWindowRect = newWindowRect;
  1747.  
  1748.     if (newWindowRect.right > (deviceRect.right - 2))
  1749.         newWindowRect.right = (deviceRect.right - 2);
  1750.  
  1751.     if (newWindowRect.bottom > (deviceRect.bottom - 2))
  1752.         newWindowRect.bottom = (deviceRect.bottom - 2);
  1753.  
  1754.     h = newWindowRect.right  - oldWindowRect.right;
  1755.     v = newWindowRect.bottom - oldWindowRect.bottom;
  1756.  
  1757.     SizeWindow(window, contentRect.right  - contentRect.left + h,
  1758.                        contentRect.bottom - contentRect.top + v, false);
  1759.         /* The window may have also changed size, due to sizeInfo or not fitting on the screen. */
  1760.  
  1761.  
  1762.     return(contentRect);
  1763. }
  1764.  
  1765.  
  1766.  
  1767. /*****************************************************************************/
  1768.  
  1769.  
  1770.  
  1771. #pragma segment UtilMain
  1772. void    StandardAbout(short appNameStringID)
  1773. {
  1774.     StringHandle    apNameHndl;
  1775.     VersRecHndl        curVersion;
  1776.     Str255            apName;
  1777.     Str255            verNum = "\p????";
  1778.     Ptr                verNumLocation;
  1779.     OSErr            err;
  1780.  
  1781.     apNameHndl = (StringHandle)nil;
  1782.     if (appNameStringID != kUseRealAppName) {
  1783.         if (appNameStringID != kUseCreatorString)
  1784.             apNameHndl = GetString(appNameStringID);
  1785.         if (!apNameHndl)
  1786.             apNameHndl = (StringHandle) GetAppResource(gSignature, 0, &err);
  1787.     }
  1788.  
  1789.     if ((!apNameHndl) || (appNameStringID == kUseRealAppName))
  1790.         pcpy(apName, gAppName);
  1791.     else
  1792.         pcpy(apName, *apNameHndl);
  1793.  
  1794.     curVersion = (VersRecHndl) GetAppResource('vers', 1, &err);
  1795.     if (curVersion) {
  1796.         verNumLocation = (Ptr)((long)(*curVersion)->shortVersion +
  1797.                          (long)*(*curVersion)->shortVersion + 1);
  1798.         pcpy(verNum, (StringPtr)verNumLocation);
  1799.     }
  1800.  
  1801.     ParamText(apName, verNum, "\p", "\p");
  1802.  
  1803.     CenteredAlert(rStdAboutAlert, nil, nil);
  1804. }
  1805.  
  1806.  
  1807.  
  1808. /*****************************************************************************/
  1809.  
  1810.  
  1811.  
  1812. #pragma segment UtilMain
  1813. void    StandardInitialization(short callsToMoreMasters)
  1814. {
  1815.     InitToolBox();
  1816.  
  1817.     while (callsToMoreMasters--) MoreMasters();
  1818.  
  1819.     PullApplicationToFront();
  1820.     GetSystemInfo();
  1821. }
  1822.  
  1823.  
  1824.  
  1825. /*****************************************************************************/
  1826.  
  1827.  
  1828.  
  1829. #pragma segment UtilMain
  1830. void    StandardMenuSetup(short MBARID, short AppleMenuID)
  1831. {
  1832.     Handle menuBar = GetNewMBar(MBARID);            /* Read menus into menu bar. */
  1833.     if (!menuBar)
  1834.         DeathAlert(rUtilStrings, eNoMenuBar);
  1835.  
  1836.     SetMenuBar(menuBar);                            /* Install menus. */
  1837.     DisposHandle(menuBar);
  1838.     AddResMenu(GetMHandle(AppleMenuID), 'DRVR');    /* Add DA names to Apple menu. */
  1839.     DrawMenuBar();
  1840. }
  1841.  
  1842.  
  1843.  
  1844. /*****************************************************************************/
  1845.  
  1846.  
  1847.  
  1848. #pragma segment UtilMain
  1849. void    ToggleCheck(DialogPtr dlgPtr, short chkItem)
  1850. {
  1851.     short    iKind;
  1852.     Handle    iHandle;
  1853.     Rect    iRect;
  1854.  
  1855.     GetDItem(dlgPtr, chkItem, &iKind, &iHandle, &iRect);
  1856.     SetCtlValue((ControlHandle) iHandle, !GetCtlValue((ControlHandle)iHandle));
  1857. }
  1858.  
  1859.  
  1860.  
  1861. /*****************************************************************************/
  1862.  
  1863.  
  1864.  
  1865. /* Check to see if a given trap is implemented. */
  1866.  
  1867. #pragma segment UtilMain
  1868. Boolean TrapExists(short theTrap)
  1869. {
  1870.     TrapType    theTrapType;
  1871.  
  1872.     theTrapType = GetTrapType(theTrap);
  1873.     if ((theTrapType == ToolTrap) && ((theTrap &= 0x07FF) >= NumToolboxTraps()))
  1874.         theTrap = _Unimplemented;
  1875.  
  1876.     return(NGetTrapAddress(_Unimplemented, ToolTrap) != NGetTrapAddress(theTrap, theTrapType));
  1877. }
  1878.  
  1879.  
  1880.  
  1881. /*****************************************************************************/
  1882.  
  1883.  
  1884.  
  1885. #pragma segment UtilMain
  1886. Boolean    WhichControl(Point mouseLoc, WindowPtr window, ControlHandle *ctlHit)
  1887. {
  1888.     Boolean            found;
  1889.     ControlHandle    ctl;
  1890.     Rect            rct;
  1891.  
  1892.     found   = false;
  1893.     *ctlHit = nil;
  1894.  
  1895.     if (window) {
  1896.         ctl = ((WindowPeek)window)->controlList;
  1897.         while (ctl) {
  1898.             if ((*ctl)->contrlVis) {
  1899.                 rct = (*ctl)->contrlRect;
  1900.                 if (PtInRect(mouseLoc, &rct)) {
  1901.                     *ctlHit = ctl;
  1902.                     found   = true;        /* Return the last hit in the linked list, as
  1903.                                         ** it is drawn last, and therefore on top. */
  1904.                 }
  1905.             }
  1906.             ctl = (*ctl)->nextControl;
  1907.         }
  1908.     }
  1909.  
  1910.     return(found);
  1911. }
  1912.  
  1913.  
  1914.  
  1915. /*****************************************************************************/
  1916.  
  1917.  
  1918.  
  1919. /* Zoom the window to the size appropriate for the device that contains the
  1920. ** most of the window.  An additional feature is that you can state the
  1921. ** maximum that a window should be zoomed, either horizontally or vertically.
  1922. ** If you pass in a maximum of 0 for the zoom for either direction, then that
  1923. ** direction will be zoomed to fit the device. */
  1924.  
  1925. #pragma segment UtilMain
  1926. void    ZoomToWindowDevice(WindowPtr window, short maxWidth, short maxHeight,
  1927.                            short zoomDir, Boolean front)
  1928. {
  1929.      GrafPtr    oldPort;
  1930.     Rect    contentRect, structureRect, deviceRect, newRect;
  1931.     short    width, height, dx, dy;
  1932.  
  1933.     GetPort(&oldPort);
  1934.     SetPort(window);
  1935.     EraseRect(&window->portRect);         /* Recommended for cosmetic reasons. */
  1936.  
  1937.     /* If there is the possibility of multiple gDevices, then we must check them to
  1938.     ** make sure we are zooming onto the right display device when zooming out. */
  1939.  
  1940.     if (zoomDir == inZoomOut) {
  1941.  
  1942.         contentRect      = GetWindowContentRect(window);
  1943.         structureRect = GetWindowStructureRect(window);
  1944.         deviceRect      = GetWindowDeviceRectNMB(window);
  1945.  
  1946.         deviceRect.left   += (contentRect.left - structureRect.left + 2);
  1947.         deviceRect.top    += (contentRect.top - structureRect.top + 2);
  1948.         deviceRect.right  -= (structureRect.right - contentRect.right + 1);
  1949.         deviceRect.bottom -= (structureRect.bottom - contentRect.bottom + 1);
  1950.         newRect = deviceRect;
  1951.  
  1952.         if (maxWidth)
  1953.             if ((width = deviceRect.right - deviceRect.left) > maxWidth)
  1954.                 newRect.right = (newRect.left = contentRect.left) + maxWidth;
  1955.         if (maxHeight)
  1956.             if ((height = deviceRect.bottom - deviceRect.top) > maxHeight)
  1957.                 newRect.bottom = (newRect.top = contentRect.top) + maxHeight;
  1958.         if ((dx = deviceRect.left - newRect.left) < 0)
  1959.             if ((dx = deviceRect.right - newRect.right) > 0)
  1960.                 dx = 0;
  1961.         if ((dy = deviceRect.top - newRect.top) < 0)
  1962.             if ((dy = deviceRect.bottom - newRect.bottom) > 0)
  1963.                 dy = 0;
  1964.         OffsetRect(&newRect, dx, dy);
  1965.  
  1966.         (*(WStateDataHandle)(((WindowPeek)window)->dataHandle))->stdState = newRect;
  1967.             /* Set up the WStateData record for this window. */
  1968.     }
  1969.  
  1970.     ZoomWindow(window, zoomDir, front);
  1971.     SetPort(oldPort);
  1972. }
  1973.  
  1974.  
  1975.  
  1976. /*****************************************************************************/
  1977. /*****************************************************************************/
  1978. /*****************************************************************************/
  1979.  
  1980.  
  1981.  
  1982. #pragma segment UtilMain
  1983. pascal Boolean    AlertFilter(DialogPtr dlg, EventRecord *event, short *item)
  1984. {
  1985.     short    what, theChr, theMod, handled;
  1986.  
  1987.     what = event->what;
  1988.     if (event->what == keyDown) {
  1989.         theChr = event->message   & charCodeMask;
  1990.         theMod = event->modifiers & keyCodeMask;
  1991.         if ((theChr != 0x0D) && (theChr != 0x03))
  1992.             event->what = nullEvent;
  1993.         if (theMod & (cmdKey + optionKey + controlKey))
  1994.             event->what = nullEvent;
  1995.     }
  1996.     handled = KeyEquivFilter(dlg, event, item);
  1997.     event->what = what;
  1998.     return(handled);
  1999. }
  2000.  
  2001.  
  2002.  
  2003. /*****************************************************************************/
  2004.  
  2005.  
  2006.  
  2007. /* This code expects the key equivalents to be in item #2, which is a StatText
  2008. ** item that is located so the text is outside of the dialog.  This allows us
  2009. ** to put key equivalent information in the resource fork, so the key
  2010. ** equivalents are localizable.
  2011. **
  2012. ** An example save changes before closing or quitting res source with
  2013. ** keyEquiv info would look like:
  2014. **
  2015. ** resource 'DITL' (rYesNoCancel, purgeable) {
  2016. **     {
  2017. **         {71, 315, 91, 367}, Button     { enabled, "Save" },
  2018. **         {0, -1000, 20, 2},  StaticText { disabled,
  2019. **             "=S190001,=s190001,=D190003,=d190003,=.190104,1B190004" },
  2020. **         {71, 80, 91, 162},  Button { enabled, "Don’t Save" },
  2021. **         {71, 244, 91, 302}, Button { enabled, "Cancel" },
  2022. **         {11, 78, 61, 366},  StaticText { disabled,
  2023. **             "Save changes to the document “^0” before ^1?" },
  2024. **         {11, 23, 43, 55},        Icon { disabled, 2 }
  2025. **     }
  2026. ** };
  2027. **
  2028. ** The document name would be the string for param #0.
  2029. ** The text "closing" or "quitting" would be the string for param #1.
  2030. **
  2031. ** The keyEquiv entry is item #2, which has a rect that pushes it out of the
  2032. ** dialog.  The string info is interpreted as to what the key/modifier combo
  2033. ** is, and what dialog item it relates to.
  2034. **
  2035. ** A single key equiv entry is 8 characters.  Entries are separated by commas.
  2036. **
  2037. ** If the first character of an entry is an =, then the next character is the
  2038. ** key.  If the first character isn't an =, then the first two characters are
  2039. ** the hex value of the key.  (Ex:  =S or =s for save, 1B for ESC.)
  2040. **
  2041. ** If the key pressed is the same as the key value for any of the entries, then
  2042. ** the next two characters are the hex value for which modifiers to test.  This
  2043. ** modifier test value is anded with the modifier.  The result is then compared
  2044. ** to the value of the next two hex digits.  If they are equal, then the
  2045. ** modifiers are correct, as well as the key.  If this is so, we have a winner.
  2046. **
  2047. ** "=S190001,=s190001,=D190003,=d190003,=.190104,1B190004"
  2048. **
  2049. ** The above string breaks down as follows:
  2050. ** =S190001  =S  if event keypress is an S, check the modifier values
  2051. **           19  check controlKey/optionKey/cmdKey
  2052. **           00  all modifiers we are testing for should be false
  2053. **           01  if above is true, keypress maps to item # 1
  2054. ** =s190001  Same as =S, but lowercase
  2055. ** =D190001  Same as =S, but maps to item #3
  2056. ** =d190001  Same as =D, but lowercase
  2057. ** =.190104  =.  if event keypress is a period, check the modifier values
  2058. **           19  check controlKey/optionKey/cmdKey
  2059. **           01  controlKey/optionKey should be false, cmdKey should be true
  2060. **           04  if above is true, keypress maps to item # 4
  2061. ** 1B190004  1B  if event keypress is an ESC, check the modifier values
  2062. **           19  check controlKey/optionKey/cmdKey
  2063. **           00  all modifiers we are testing for should be false
  2064. **           04  if above is true, keypress maps to item # 4
  2065. */
  2066.  
  2067. #pragma segment UtilMain
  2068. pascal Boolean    KeyEquivFilter(DialogPtr dlg, EventRecord *event, short *item)
  2069. {
  2070.     short    itemType;
  2071.     Handle    itemHndl;
  2072.     Rect    itemRect;
  2073.     Str255    itemText;
  2074.     short    i, theChr, theMod, equivChr, modMask, modVal, itemNum;
  2075.  
  2076.     if (event->what == updateEvt) {
  2077.         if (dlg == (DialogPtr)event->message)
  2078.             OutlineDialogItem(dlg, 1);
  2079.         return(false);
  2080.     }
  2081.  
  2082.     if (event->what != keyDown) return(false);
  2083.  
  2084.     itemNum = 0;
  2085.  
  2086.     theChr = event->message   & charCodeMask;
  2087.     theMod = event->modifiers & keyCodeMask;
  2088.  
  2089.     if ((theChr == 0x0D) || (theChr == 0x03)) {        /* If return or enter... */
  2090.         if (!(theMod & (cmdKey + optionKey + controlKey))) {
  2091.             *item = 1;
  2092.             return(true);
  2093.         }
  2094.     }
  2095.  
  2096.     GetDItem(dlg, 2, &itemType, &itemHndl, &itemRect);
  2097.     if (itemHndl) {
  2098.         GetIText(itemHndl, itemText);
  2099.         for (i = 1; i <= *itemText; i += 9) {
  2100.             equivChr = GetHexByte((char *)(itemText + i));
  2101.             modMask  = GetHexByte((char *)(itemText + i + 2)) << 8;
  2102.             modVal   = GetHexByte((char *)(itemText + i + 4)) << 8;
  2103.             itemNum  = GetHexByte((char *)(itemText + i + 6));
  2104.             if (theChr == equivChr)
  2105.                 if ((theMod & modMask) == modVal) break;
  2106.             itemNum = 0;
  2107.         }
  2108.     }
  2109.  
  2110.     if (itemNum) {
  2111.         GetDItem(dlg, itemNum, &itemType, &itemHndl, &itemRect);
  2112.         SelectButton((ControlHandle)itemHndl);
  2113.         *item = itemNum;
  2114.         return(true);
  2115.     }
  2116.  
  2117.     return(false);
  2118. }
  2119.  
  2120.  
  2121.  
  2122. /*****************************************************************************/
  2123.  
  2124.  
  2125.  
  2126. #pragma segment UtilMain
  2127. void    OffsetControl(ControlHandle ctl, short dx, short dy)
  2128. {
  2129.     Rect    ctlRect;
  2130.  
  2131.     ctlRect = (*ctl)->contrlRect;
  2132.     MoveControl(ctl, ctlRect.left + dx, ctlRect.top + dy);
  2133. }
  2134.  
  2135.  
  2136.  
  2137. /*****************************************************************************/
  2138.  
  2139.  
  2140.  
  2141. #pragma segment UtilMain
  2142. void    DoDrawGrowIcon(WindowPtr window, Boolean horLine, Boolean verLine)
  2143. {
  2144.     WindowPtr    oldPort;
  2145.     Rect        rct;
  2146.     RgnHandle    oldClip, newClip;
  2147.  
  2148.     GetPort(&oldPort);
  2149.     SetPort(window);
  2150.  
  2151.     rct = window->portRect;
  2152.     rct.left = rct.right  - 15;
  2153.     rct.top  = rct.bottom - 15;
  2154.  
  2155.     if (!((WindowPeek)window)->hilited) {
  2156.         FrameRect(&rct);
  2157.         ++rct.top;
  2158.         ++rct.left;
  2159.         EraseRect(&rct);
  2160.         SetPort(oldPort);
  2161.         return;
  2162.     }
  2163.  
  2164.     oldClip = NewRgn();
  2165.     newClip = NewRgn();
  2166.  
  2167.     if (horLine)
  2168.         rct.left = window->portRect.left;
  2169.     if (verLine)
  2170.         rct.top  = window->portRect.top;
  2171.     RectRgn(newClip, &rct);
  2172.  
  2173.     GetClip(oldClip);
  2174.     SetClip(newClip);
  2175.     DrawGrowIcon(window);        /* Draw grow icon without scrollbar lines. */
  2176.  
  2177.     SetClip(oldClip);
  2178.     DisposeRgn(oldClip);
  2179.     DisposeRgn(newClip);
  2180.  
  2181.     SetPort(oldPort);
  2182. }
  2183.  
  2184.  
  2185.  
  2186. /*****************************************************************************/
  2187.  
  2188.  
  2189.  
  2190. #pragma segment UtilMain
  2191. void    DoDrawControls(WindowPtr window, Boolean scrollBarsOnly)
  2192. {
  2193.     ControlHandle    ctl;
  2194.  
  2195.     ctl = ((WindowPeek)window)->controlList;
  2196.     while (ctl) {
  2197.         DoDraw1Control(ctl, scrollBarsOnly);
  2198.         ctl = (*ctl)->nextControl;
  2199.     }
  2200. }
  2201.  
  2202.  
  2203.  
  2204. /*****************************************************************************/
  2205.  
  2206.  
  2207.  
  2208. #pragma segment UtilMain
  2209. void    DoDraw1Control(ControlHandle ctl, Boolean scrollBarsOnly)
  2210. {
  2211.     WindowPtr        window, oldPort;
  2212.     Rect            rct;
  2213.  
  2214.     if (IsScrollBar(ctl)) {
  2215.         window = (*ctl)->contrlOwner;
  2216.         if (((WindowPeek)window)->hilited)
  2217.             Draw1Control(ctl);
  2218.         else {
  2219.             if ((*ctl)->contrlVis) {
  2220.                 GetPort(&oldPort);
  2221.                 SetPort(window);
  2222.                 rct = (*ctl)->contrlRect;
  2223.                 FrameRect(&rct);
  2224.                 InsetRect(&rct, 1, 1);
  2225.                 EraseRect(&rct);
  2226.                 SetPort(oldPort);
  2227.             }
  2228.         }
  2229.     }
  2230.     else
  2231.         if (!scrollBarsOnly)
  2232.             Draw1Control(ctl);
  2233. }
  2234.  
  2235.  
  2236.  
  2237. /*****************************************************************************/
  2238.  
  2239.  
  2240.  
  2241. /* GetPopupCtlHandle takes a dialog and its item number and (assuming it is a
  2242. ** popup menu control) and returns the control handle for the popup. */
  2243.  
  2244. #pragma segment UtilMain
  2245. ControlHandle    GetPopupCtlHandle(DialogPtr theDialog, short itemNum)
  2246. {
  2247.     short        theType;
  2248.     Handle        theHndl;
  2249.     Rect        theBox;
  2250.  
  2251.     GetDItem(theDialog, itemNum, &theType, &theHndl, &theBox);
  2252.     return((ControlHandle)theHndl);
  2253. }
  2254.  
  2255.  
  2256.  
  2257. /*****************************************************************************/
  2258.  
  2259.  
  2260.  
  2261. /* GetPopupMenuHandle takes a popup control and returns the menu handle from
  2262. ** the control. */
  2263.  
  2264. #pragma segment UtilMain
  2265. MenuHandle    GetPopupMenuHandle(ControlHandle popupCtl)
  2266. {
  2267.     PopupCtlDataHandle    popupData;
  2268.  
  2269.     if (popupData = (PopupCtlDataHandle)(*popupCtl)->contrlData)
  2270.         return((*popupData)->mHandle);
  2271.  
  2272.     return(nil);
  2273. }
  2274.  
  2275.  
  2276.  
  2277. /*****************************************************************************/
  2278.  
  2279.  
  2280.  
  2281. /* GetPopupCtlValue returns value for the popup control. */
  2282.  
  2283. #pragma segment UtilMain
  2284. short    GetPopupCtlValue(DialogPtr theDialog, short popItem)
  2285. {
  2286.     ControlHandle    popupCtl;
  2287.  
  2288.     if (popupCtl = GetPopupCtlHandle(theDialog, popItem))
  2289.         return(GetCtlValue(popupCtl));
  2290.  
  2291.     return(-1);
  2292. }
  2293.  
  2294.  
  2295.  
  2296. /*****************************************************************************/
  2297.  
  2298.  
  2299.  
  2300. /* SetPopupCtlValue makes value the new value for the popup control. */
  2301.  
  2302. #pragma segment UtilMain
  2303. void    SetPopupCtlValue(DialogPtr theDialog, short popItem, short value)
  2304. {
  2305.     ControlHandle    popupCtl;
  2306.  
  2307.     if (popupCtl = GetPopupCtlHandle(theDialog, popItem)) {
  2308.         (*popupCtl)->contrlValue = value;
  2309.         Draw1Control(popupCtl);
  2310.     }
  2311. }
  2312.  
  2313.  
  2314.  
  2315. /*****************************************************************************/
  2316.  
  2317.  
  2318.  
  2319. /* This is used to "intelligently" insert a menu item into a menu.  Pass it
  2320. ** the menu to be modified, the text of the item being added, plus where the
  2321. ** item is to be inserted.  The location to be inserted is described by two
  2322. ** parameters:  section & where.
  2323. **
  2324. ** section:  Indicates which group of menu items you wish to add an item to.
  2325. **           Menu item section 1 is all of the items before the first
  2326. **           dividing line.  Menu item section 2 is all items after the
  2327. **           first dividing line and before the second, and so on.  If you
  2328. **           have no dividing lines, you have just 1 section so pass in 1.
  2329. **
  2330. ** where:    Indicates the item position relative to the section.  To add an
  2331. **           item such that it is the first item in a section, pass in a 1.
  2332. **           It will be added in front of the first item in the section.
  2333. **
  2334. **           NOTE:  You should never pass in a section or where parameter of 0.
  2335. **
  2336. ** Negative values for "where" are magic.  If where = kMenuItemTxtInsert, then
  2337. ** it inserts the item alphabetically into the section.  A where of
  2338. ** kMenuItemNumInsert works the same as kMenuItemTxtInsert, except it treats
  2339. ** the strings are numbers for comparison purposes.  If you want to add the
  2340. ** item to the end of a section, use kMenuItemSectionEnd.
  2341. **
  2342. ** As a final goodie, SmartInsMenuItem returns the menu item # from the
  2343. ** beginning of the menu, not section.
  2344. */
  2345.  
  2346. #pragma segment UtilMain
  2347. short    SmartInsMenuItem(MenuHandle theMenu, StringPtr theText, short section, short where)
  2348. {
  2349.     short    numItems, base, i;
  2350.     short    insertType, val;
  2351.     Str255    cmpTxt, txt;
  2352.  
  2353.     numItems = CountMItems(theMenu);    /* Total number of items in menu. */
  2354.  
  2355.     if (--section < 0)
  2356.         section = 0;                    /* We want section 0-based. */
  2357.  
  2358.     for (base = 0, i = 1; (section) && (i <= numItems); ++i) {
  2359.         GetItem(theMenu, base + i, txt);
  2360.         if (txt[1] == '-') {
  2361.             base = i;
  2362.             --section;
  2363.         }
  2364.     }        /* base now tells us our section starting offset. */
  2365.  
  2366.     if (where < 0) {        /* If magic mode... */
  2367.  
  2368.         InsMenuItem(theMenu, theText, 0);        /* Take out meta characters */
  2369.         GetItem(theMenu, 1, cmpTxt);            /* for comparison purposes. */
  2370.         DelMenuItem(theMenu, 1);
  2371.  
  2372.         insertType = where;
  2373.         val = p2num(cmpTxt, 10, nil);
  2374.  
  2375.         for (where = 1; i <= (numItems - base); ++where) {
  2376.             GetItem(theMenu, where + base, txt);
  2377.             if (txt[1] == '-') break;
  2378.             if ((insertType == kMenuItemTxtInsert) && ((IUCompString(cmpTxt, txt) < 0))) break;
  2379.             if ((insertType == kMenuItemNumInsert) && (val < p2num(txt, 10, nil)))       break;
  2380.         }
  2381.     }
  2382.  
  2383.     where += base;
  2384.     InsMenuItem(theMenu, theText, where - 1);        /* InsMenuItem does an insert-after. */
  2385.  
  2386.     return(where);
  2387. }
  2388.  
  2389.  
  2390.  
  2391. /*****************************************************************************/
  2392.  
  2393.  
  2394.  
  2395. #pragma segment UtilMain
  2396. short    CountMSections(MenuHandle theMenu)
  2397. {
  2398.     short    numItems, numSections, i;
  2399.     Str255    txt;
  2400.  
  2401.     numItems = CountMItems(theMenu);    /* Total number of items in menu. */
  2402.  
  2403.     for (numSections = i = 1; i <= numItems; ++i) {
  2404.         GetItem(theMenu, i, txt);
  2405.         if (txt[1] == '-')
  2406.             ++numSections;
  2407.     }
  2408.  
  2409.     return(numSections);
  2410. }
  2411.  
  2412.  
  2413.  
  2414. /*****************************************************************************/
  2415.  
  2416.  
  2417.  
  2418. #pragma segment UtilMain
  2419. short    FindMenuItem(MenuHandle theMenu, StringPtr cmpTxt)
  2420. {
  2421.     short    item;
  2422.     Str255    txt;
  2423.  
  2424.     for (item = CountMItems(theMenu); item; --item) {
  2425.         GetItem(theMenu, item, txt);
  2426.         if (!IUCompString(cmpTxt, txt)) break;
  2427.     }
  2428.  
  2429.     return(item);
  2430. }
  2431.  
  2432.  
  2433.  
  2434. /*****************************************************************************/
  2435.  
  2436.  
  2437.  
  2438. #pragma segment UtilMain
  2439. OSErr    PersistFSSpec(PFSSpecPtr pfss)
  2440. {
  2441.     OSErr            err;
  2442.     HParamBlockRec    pb;
  2443.     char            delim;
  2444.  
  2445.     memset(&pb, 0, sizeof(HParamBlockRec));        /* Make us a happy ParamBlock. */
  2446.     pb.volumeParam.ioNamePtr = pfss->volName;
  2447.  
  2448.     if (!(pfss->fss.name[0])) {                /* If no file name, then there's no file. */
  2449.         pfss->volName[0] = 0;                /* Zap all remnants of file specification. */
  2450.         pfss->fss.vRefNum = 0;
  2451.         return(noErr);
  2452.     }
  2453.  
  2454.     if (pb.volumeParam.ioVRefNum = pfss->fss.vRefNum) {
  2455.         pfss->volName[0] = 0;    /* If we are passed in a vRefNum, then we are
  2456.                                 ** wanting the volume name.  This is what we are
  2457.                                 ** looking to get, so show it as currently missing. */
  2458.         err = PBHGetVInfo(&pb, false);
  2459.     }
  2460.     else {
  2461.         if (!(pfss->volName[0])) return(noErr);
  2462.  
  2463.         pb.volumeParam.ioVolIndex = -1;        /* Use the name to find the vRefNum. */
  2464.         delim = (gAUXVersion) ? '/' : ':';
  2465.         if (pfss->volName[pfss->volName[0]] != delim)
  2466.             pfss->volName[++(pfss->volName[0])] = delim;
  2467.                 /* Make sure that volume name ends with a delimiter. */
  2468.  
  2469.         if (!(err = PBHGetVInfo(&pb, false)))
  2470.             pfss->fss.vRefNum = pb.volumeParam.ioVRefNum;
  2471.     }
  2472.  
  2473.     return(err);
  2474. }
  2475.  
  2476.  
  2477.  
  2478. /*****************************************************************************/
  2479.  
  2480.  
  2481.  
  2482. #pragma segment UtilMain
  2483. StringPtr    PathNameFromDirID(long dirID, short vRefNum, StringPtr str)
  2484. {
  2485.     CInfoPBRec    block;
  2486.     Str255        directoryName;
  2487.  
  2488.     *str = 0;
  2489.     block.dirInfo.ioNamePtr = directoryName;
  2490.     block.dirInfo.ioDrParID = dirID;
  2491.  
  2492.     do {
  2493.         block.dirInfo.ioVRefNum   = vRefNum;
  2494.         block.dirInfo.ioFDirIndex = -1;
  2495.         block.dirInfo.ioDrDirID   = block.dirInfo.ioDrParID;
  2496.  
  2497.         if (PBGetCatInfo(&block, false)) {
  2498.             *str = 0;
  2499.             break;
  2500.         }
  2501.  
  2502.         if (gAUXVersion) {
  2503.             if (directoryName[1] != '/')
  2504.                 pcat(directoryName, "\p/");
  2505.                     /* If this isn't root (i.e. '/'), append a slash ('/'). */
  2506.         } else pcat(directoryName, "\p:");
  2507.             /* Append a Macintosh style colon (':'). */
  2508.  
  2509.         pcat(directoryName, str);
  2510.         pcpy(str, directoryName);
  2511.  
  2512.     } while (block.dirInfo.ioDrDirID != fsRtDirID);
  2513.  
  2514.     return(str);
  2515. }
  2516.  
  2517.  
  2518.  
  2519. /*****************************************************************************/
  2520.  
  2521.  
  2522.  
  2523. #pragma segment UtilMain
  2524. void    InitQuickTime(void)
  2525. {
  2526.     ComponentDescription    controllerDescriptor;
  2527.  
  2528.     if (!gQTVersion) {
  2529.         if (!(Gestalt(gestaltQuickTime, &gQTVersion))) {
  2530.             if (EnterMovies())
  2531.                 gQTVersion = 0;
  2532.             else {
  2533.                 controllerDescriptor.componentType         = 'play';
  2534.                 controllerDescriptor.componentSubType      = 0;
  2535.                 controllerDescriptor.componentManufacturer = 0;
  2536.                 controllerDescriptor.componentFlags        = 0;
  2537.                 controllerDescriptor.componentFlagsMask    = 0;
  2538.                 gMovieControllerComponent = FindNextComponent((Component)0, &controllerDescriptor);
  2539.             }
  2540.         }
  2541.     }
  2542. }
  2543.  
  2544.  
  2545.  
  2546.